package com.cmc6.role.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cmc6.common.exception.BaseBizCodeEnum;
import com.cmc6.common.mapper.RoleMapper;
import com.cmc6.common.model.dto.NotEmptyIdSet;
import com.cmc6.common.model.dto.NotNullId;
import com.cmc6.common.model.entity.*;
import com.cmc6.common.util.ApiResult;
import com.cmc6.common.util.MyEntityUtil;
import com.cmc6.role.exception.BizCodeEnum;
import com.cmc6.role.model.dto.RoleInsertOrUpdateDTO;
import com.cmc6.role.model.dto.RolePageDTO;
import com.cmc6.role.model.vo.RolePageVO;
import com.cmc6.role.service.RoleRefMenuService;
import com.cmc6.role.service.RoleRefUserService;
import com.cmc6.role.service.RoleService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, RoleDO> implements RoleService {

    @Resource
    RoleRefMenuService roleRefMenuService;
    @Resource
    RoleRefUserService roleRefUserService;

    /**
     * 新增/修改角色
     */
    @Override
    @Transactional
    public String insertOrUpdate(RoleInsertOrUpdateDTO dto) {

        // 角色名（不能重复）
        Long count =
            lambdaQuery().eq(RoleDO::getName, dto.getName()).ne(dto.getId() != null, BaseEntityTwo::getId, dto.getId())
                .count();
        if (count != 0) {
            ApiResult.error(BizCodeEnum.THE_SAME_ROLE_NAME_EXISTS);
        }

        // 如果是默认角色，则取消之前的默认角色
        if (dto.isDefaultFlag()) {
            lambdaUpdate().set(RoleDO::getDefaultFlag, false).eq(RoleDO::getDefaultFlag, true)
                .ne(dto.getId() != null, BaseEntityTwo::getId, dto.getId()).update();
        }

        RoleDO roleDO = new RoleDO();
        roleDO.setName(dto.getName());
        roleDO.setDefaultFlag(dto.isDefaultFlag());
        roleDO.setEnableFlag(dto.isEnableFlag());
        roleDO.setRemark(MyEntityUtil.getNotNullStr(dto.getRemark()));
        roleDO.setId(dto.getId());

        if (dto.getId() == null) {
            // 新增
            baseMapper.insert(roleDO);
        } else {
            // 修改
            baseMapper.updateById(roleDO);
            // 先删除子表数据
            deleteByIdSetSub(Collections.singleton(dto.getId()));
        }

        // 再插入子表数据
        if (CollUtil.isNotEmpty(dto.getMenuIdSet())) {
            List<RoleRefMenuDO> dbList = new ArrayList<>();
            for (Long menuId : dto.getMenuIdSet()) {
                RoleRefMenuDO roleRefMenuDO = new RoleRefMenuDO();
                roleRefMenuDO.setRoleId(roleDO.getId());
                roleRefMenuDO.setMenuId(menuId);
                dbList.add(roleRefMenuDO);
            }
            roleRefMenuService.saveBatch(dbList);
        }
        if (CollUtil.isNotEmpty(dto.getUserIdSet())) {
            List<RoleRefUserDO> dbList = new ArrayList<>();
            for (Long userId : dto.getUserIdSet()) {
                RoleRefUserDO roleRefUserDO = new RoleRefUserDO();
                roleRefUserDO.setRoleId(roleDO.getId());
                roleRefUserDO.setUserId(userId);
                dbList.add(roleRefUserDO);
            }
            roleRefUserService.saveBatch(dbList);
        }

        return BaseBizCodeEnum.API_RESULT_OK.getMsg();
    }

    /**
     * 分页排序查询：角色
     */
    @Override
    public Page<RoleDO> myPage(RolePageDTO dto) {

        return lambdaQuery().like(StrUtil.isNotBlank(dto.getName()), RoleDO::getName, dto.getName())
            .like(StrUtil.isNotBlank(dto.getRemark()), BaseEntityThree::getRemark, dto.getRemark())
            .eq(dto.getId() != null, BaseEntityTwo::getId, dto.getId())
            .eq(dto.getEnableFlag() != null, BaseEntityThree::getEnableFlag, dto.getEnableFlag())
            .eq(dto.getDefaultFlag() != null, RoleDO::getDefaultFlag, dto.getDefaultFlag()).page(dto.getPage());

    }

    /**
     * 通过主键id，查看详情
     */
    @Override
    public RolePageVO infoById(NotNullId notNullId) {

        RoleDO roleDO = getById(notNullId.getId());
        if (roleDO == null) {
            return null;
        }

        RolePageVO resVO = BeanUtil.copyProperties(roleDO, RolePageVO.class);

        // 完善子表的数据
        List<RoleRefMenuDO> menuList = roleRefMenuService.lambdaQuery().eq(RoleRefMenuDO::getRoleId, resVO.getId())
            .select(RoleRefMenuDO::getMenuId).list();

        List<RoleRefUserDO> userList = roleRefUserService.lambdaQuery().eq(RoleRefUserDO::getRoleId, resVO.getId())
            .select(RoleRefUserDO::getUserId).list();

        resVO.setUserIdSet(userList.stream().map(RoleRefUserDO::getUserId).collect(Collectors.toSet()));
        resVO.setMenuIdSet(menuList.stream().map(RoleRefMenuDO::getMenuId).collect(Collectors.toSet()));

        return resVO;
    }

    /**
     * 删除角色
     */
    @Override
    @Transactional
    public String deleteByIdSet(NotEmptyIdSet notEmptyIdSet) {

        deleteByIdSetSub(notEmptyIdSet.getIdSet()); // 删除子表数据

        baseMapper.deleteBatchIds(notEmptyIdSet.getIdSet());

        return BaseBizCodeEnum.API_RESULT_OK.getMsg();
    }

    /**
     * 删除子表数据
     */
    private void deleteByIdSetSub(Set<Long> idSet) {

        // 删除 角色菜单关联表
        roleRefMenuService.removeByIds(idSet);
        // 删除 角色用户关联表
        roleRefUserService.removeByIds(idSet);

    }

}




